#include "FabricaDeComponentes.h"
#include "GestorArchivoConfiguracion.h"
#include "Util.h"
#include "GraficoTablaComun.h"
#include "GraficoTorta.h"
#include "GraficoBarras.h"

class Cliente;

void stringSplitter(std::string& linea, std::string& nombre, std::vector<std::string>& tokens) {
	std::stringstream ss(linea);
	std::string s1;
	ss >> s1;
	if(s1 == "Tabla") {
		std::string s2;
		ss >> s2;
		s1.push_back(' ');
		s1.append(s2);
	}
	nombre = s1;
	char buffer[300];
	ss.getline(buffer, 300);
	std::string sNuevo(buffer);
	int pos = 0;
	while(sNuevo.find('|', pos) != std::string::npos) {
		std::string sAux = sNuevo.substr(pos, sNuevo.find('|', pos) - pos);
		pos = sNuevo.find('|', pos);
		tokens.push_back(sAux);
		++pos;
	}
	std::string sAux2 = sNuevo.substr(pos, 300);
	tokens.push_back(sAux2);
}


FabricaDeComponentes::FabricaDeComponentes(ParserConsultas &parser, GestorArchivoConfiguracion& gestor):
	parserConsultas(parser), gestorConfig(gestor) {
	setAgregaciones();
}


std::vector<std::string> &FabricaDeComponentes::getDatosDeTablas() {
	return datosDeTablas;
}

std::vector<FrameConsulta*>& FabricaDeComponentes::getFramesDeTabla(std::string &nombreTabla) {
	return framesDeConsulta[nombreTabla];
}

const std::string& FabricaDeComponentes::getNombreDeTabla(std::string &datosDeTabla) {
	return nombresDeTablas[datosDeTabla];
}

void FabricaDeComponentes::crearComponentes(Cliente *cliente) {
	Portal* portal = NULL;
	Grafico* grafico = NULL;
	FrameConsulta* frame = NULL;
	unsigned int cantidadConsultasPorTabla = 0;
	unsigned int numeroFrame = 0;
	datosDeTablas = parserConsultas.getDatosDeTablas();

	std::vector<std::string>::iterator it = datosDeTablas.begin();

	for(; it != datosDeTablas.end(); it++) {
		cantidadConsultasPorTabla = parserConsultas.getCantidadconsultasDeTabla(*it);
		nombresDeTablas[*it] = parserConsultas.getNombreTabla(*it);

		for(unsigned int i = 1; i <= cantidadConsultasPorTabla; i++) {
			numeroFrame++;

			portal = crearPortal(*it, i, cliente);
			portal->setNumeroConsulta(numeroFrame);	//el numerodeframeesunicoasiqueesusadoparacrearconsultas
			portal->setGestorConfiguracion(&gestorConfig);

			grafico = crearGrafico(*it, i);

			frame = Gtk::manage(new FrameConsulta(numeroFrame));
			frame->setComponentes(portal, grafico);
			framesDeConsulta[*it].push_back(frame);
		}
	}
}


Portal* FabricaDeComponentes::crearPortal(std::string &datosTabla, unsigned int numeroDeConsulta, Cliente* cliente) {
	unsigned int numeroFilas;
	std::vector<std::string> valoresFiltros;
	std::vector<std::string> valoresInputsD;	// son los nombre de los inputs y no el contenido del comboBox
	std::vector<std::string> valoresInputsH;
	unsigned int numeroTabla = parserConsultas.getNumeroTabla(datosTabla);

	// muy ineficiente
	if(parserConsultas.hayFiltro(datosTabla, numeroDeConsulta))
		valoresFiltros = parserConsultas.getFiltros(datosTabla, numeroDeConsulta);
	if(parserConsultas.hayInputDimension(datosTabla, numeroDeConsulta))
		 valoresInputsD = parserConsultas.getInputsDimensiones(datosTabla, numeroDeConsulta);
	if(parserConsultas.hayInputHecho(datosTabla, numeroDeConsulta))
		valoresInputsH = parserConsultas.getInputsHechos(datosTabla, numeroDeConsulta);

	numeroFilas = valoresFiltros.size() + valoresInputsD.size() + valoresInputsH.size();

	Portal* portal = Gtk::manage(new Portal(numeroFilas, numeroTabla));

	if(!valoresFiltros.empty())
		portal->setValoresFiltro(valoresFiltros);

	std::vector<std::string> vectorVacio;
	if(!valoresInputsD.empty()) {
		std::vector<std::string>::iterator iteradorDimension = valoresInputsD.begin();
		for(; iteradorDimension != valoresInputsD.end(); iteradorDimension++) { // ineficiente
			//* RECORDAR QUE SI ES UNA DIMENSION FECHA, NO SE NECESITA LLAMAR AL SERVER
			// falta hacer fecha
			// POR AHORA SE LLENA CON BASURA

			portal->setInputs(*iteradorDimension, vectorVacio);
		}
	}

	if(!valoresInputsH.empty()) {
		std::vector<std::string>::iterator iteradorHecho = valoresInputsH.begin();
		for(; iteradorHecho != valoresInputsH.end(); iteradorHecho++) { // ineficiente
			/*
			 * FALTA TENER EN CUENTA LOS OTROS TIPOS DE INPUTS HECHOS, fechas y < > =
		 	 */
			portal->setInputs(*iteradorHecho, agregaciones);
		}
	}
	return portal;
}

Grafico* FabricaDeComponentes::crearGrafico(std::string &datosTabla, unsigned int numeroConsulta) {
	std::string linea = parserConsultas.getGrafico(datosTabla, numeroConsulta);
	std::vector<std::string> vec;
	std::string nombre;

	/**** invoca al metodo y pasale los parametros*/
	stringSplitter(linea, nombre, vec);
	/*harcodeado*/
	//nombre = "Tabla Simple";
	//vec.push_back("Vendedor");	vec.push_back("Sucursal");	vec.push_back("Precio");	vec.push_back("Producto");
	/* fin hardcodeo*/

	if(nombre.compare(Util::GTABLACOMUN) == 0)
		return Gtk::manage(new GraficoTablaComun(vec.size(),vec));
	if(nombre.compare(Util::GTABLACOMUN) == 0)
		return Gtk::manage(new GraficoTablaComun(vec.size(),vec));
	if(nombre.compare(Util::GTABLACOMUN) == 0)
		return Gtk::manage(new GraficoTablaComun(vec.size(),vec));


	return NULL;	//nodebe sucedeer sino explota, pero para q compile por ahora
}

void FabricaDeComponentes::setAgregaciones() {
	agregaciones.push_back(Util::SNONE);
	agregaciones.push_back(Util::SSUM);
	agregaciones.push_back(Util::SMAX);
	agregaciones.push_back(Util::SMIN);
	agregaciones.push_back(Util::SAVG);
	agregaciones.push_back(Util::SCOUNT);
}














